package org.example.shop_front_api.utils;

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;

public class SignatureUtils {

    /**
     * 生成接口签名
     * @param params 请求参数（Map形式，key-value）
     * @param secretKey 共享密钥
     * @return 签名字符串
     */
    public static String generateSignature(Map<String, String> params, String secretKey) {
        // 1. 校验并添加必要参数（时间戳、随机串）
        if (!params.containsKey("timestamp")) {
            params.put("timestamp", String.valueOf(System.currentTimeMillis())); // 毫秒时间戳
        }
        if (!params.containsKey("nonce")) {
            params.put("nonce", UUID.randomUUID().toString().replaceAll("-", "")); // 随机串
        }

        // 2. 移除可能存在的"sign"参数（避免循环签名）
        params.remove("sign");

        // 3. 对参数按key进行ASCII升序排序
        List<String> keyList = new ArrayList<>(params.keySet());
        Collections.sort(keyList); // 排序后参数顺序固定

        // 4. 拼接参数为"key=value&key=value"格式
        StringBuilder paramStr = new StringBuilder();
        for (String key : keyList) {
            String value = params.get(key);
            if (value != null && !value.isEmpty()) { // 忽略空值参数
                paramStr.append(key).append("=").append(value).append("&");
            }
        }
        // 移除最后一个"&"
        if (paramStr.length() > 0) {
            paramStr.deleteCharAt(paramStr.length() - 1);
        }

        // 5. 拼接密钥（通常在字符串末尾）
        String signSource = paramStr.toString() + secretKey;

        // 6. 使用SHA256生成签名（转大写）
        return sha256(signSource).toUpperCase();
    }

    /**
     * SHA256哈希算法
     * @param str 待哈希字符串
     * @return 哈希结果（十六进制）
     */
    private static String sha256(String str) {
        try {
            MessageDigest digest = MessageDigest.getInstance("SHA-256");
            byte[] hash = digest.digest(str.getBytes(StandardCharsets.UTF_8));
            // 转十六进制字符串
            StringBuilder hexStr = new StringBuilder();
            for (byte b : hash) {
                String hex = Integer.toHexString(0xff & b);
                if (hex.length() == 1) {
                    hexStr.append('0');
                }
                hexStr.append(hex);
            }
            return hexStr.toString();
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("SHA256算法不存在", e);
        }
    }

    /**
     * 验证签名是否合法
     * @param params 请求参数（包含签名）
     * @param secretKey 共享密钥
     * @return 验证结果（true=合法）
     */
    public static boolean verifySignature(Map<String, String> params, String secretKey) {
        // 1. 提取参数中的签名
        String receivedSign = params.get("sign");
        if (receivedSign == null || receivedSign.isEmpty()) {
            return false;
        }

        // 2. 用相同逻辑生成签名
        String generatedSign = generateSignature(new HashMap<>(params), secretKey);

        // 3. 比对签名（忽略大小写的话用equalsIgnoreCase）
        return receivedSign.equals(generatedSign);
    }
}

